package com.syyo;

import com.syyo.service.SyyoService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader;
import org.springframework.beans.factory.support.*;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.*;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.net.MalformedURLException;

/**
 *
 * Spring容器的refresh()【创建刷新】
 *
 * 1、prepareRefresh() 刷新前的预处理
 *    1）、initPropertySources();// 初始化一些属性设置
 *    2）、getEnvironment().validateRequiredProperties();//验证所有标记为required的属性都是可解析的:并设置
 *    3）、this.earlyApplicationEvents = new LinkedHashSet<>(); 保存容器中的一些事件
 *
 * 2、obtainFreshBeanFactory(); 获取beanFactory工厂
 *    1）、refreshBeanFactory(); 创建 beanFactory
 *        GenericApplicationContext 实例化，创建了一个 this.beanFactory = new DefaultListableBeanFactory()
 *        设置序列化id
 *    2）、getBeanFactory(); 返回 GenericApplicationContext创建的beanFactory;
 *
 * 3、prepareBeanFactory(beanFactory); 对象beanFactory进行一些设置
 *    1）、设置beanFactory的类加载器
 *    2）、添加BeanPostProcessor接口的实现类ApplicationContextAwareProcessor
 *    3）、设置beanFactory的忽略Aware接口【自动装配】
 *          EnvironmentAware
 *          EmbeddedValueResolverAware
 *          ResourceLoaderAware
 *          ApplicationEventPublisherAware
 *          MessageSourceAware
 *          ApplicationContextAware
 *    4）、注册可以解析的自动装配
 *          BeanFactory
 *          ResourceLoader
 *          ApplicationEventPublisher
 *          ApplicationContext
 *    5）、添加BeanPostProcessor接口的实现类ApplicationListenerDetector
 *          BeanFactory
 *          ResourceLoader
 *          ApplicationEventPublisher
 *          ApplicationContext
 *    6）、添加编译时的AspectJ
 *    7）、给容器注册一些能用的组件
 *          事件 environment
 *          系统属性 systemProperties
 *          系统事件 systemEnvironment
 *
 * 4、postProcessBeanFactory(beanFactory); beanFactory准备工作完成后进行的后缀处理工作
 *    1）、子类通过重写这个方法在beanFactory创建并预准备完成以后做进一步的设置
 *
 * ======================================beanFactory的创建和预准备工作=========================================
 *
 * 5、invokeBeanFactoryPostProcessors(beanFactory);在beanFactory初始化之后执行的，执行实现了BeanFactoryPostProcessors的接口
 *    1）、BeanFactoryPostProcessor ，BeanDefinitionRegistryPostProcessor
 *    2）、先执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry()
 *          1、获取所有的BeanDefinitionRegistryPostProcessor
 *          2、优先执行实现【PriorityOrdered】接口的BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()方法
 *          3、再执行【Ordered】接口的BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()方法
 *          4、最后执行没有实现任务优先级的接口的BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()方法
 *

 *    1）、BeanFactoryPostProcessor
 *          1、获取所有的BeanFactoryPostProcessor
 *          2、优先执行实现【PriorityOrdered】接口的 BeanFactoryPostProcessor.postProcessBeanDefinitionRegistry()方法
 *          3、再执行【Ordered】接口的 BeanFactoryPostProcessor.postProcessBeanDefinitionRegistry()方法
 *          4、最后执行没有实现任务优先级的接口的 BeanFactoryPostProcessor.postProcessBeanDefinitionRegistry()方法
 *
 *
 * 6、registerBeanPostProcessors(beanFactory); 注册bean的后置处理器
 *      BeanPostProcessor
 *      DestructionAwareBeanPostProcessor
 *      InstantiationAwareBeanPostProcessor
 *      SmartInstantiationAwareBeanPostProcessor
 *      MergedBeanDefinitionPostProcessor
 *      1）、获取所有的 BeanPostProcessor
 *      2）、根据接口的优先级【PriorityOrdered】【Ordered】的 注册到 beanFactory工厂
 *      3）、先注册实现 【PriorityOrdered】， beanFactory.addBeanPostProcessor(postProcessor)
 *      4）、再注册实现 【Ordered】
 *      5）、最后注册没有实现优先级的
 *      6）、最终注册实现【MergedBeanDefinitionPostProcessor】接口的
 *
 * 7、initMessageSource();初始化【MessageSource】组件（做国际化功能，消息绑定和解析）
 *      1）、获取bean工厂的 getBeanFactory();
 *      2）、判断有没有【messageSource】的容器bean，有就返回，没有就创建一个【DelegatingMessageSource】
 *
 * 8、initApplicationEventMulticaster();初始化事件派发器
 *      1）、获取bean工厂的 getBeanFactory();
 *      2）、判断有没有【applicationEventMulticaster】的容器bean，有就返回，没有就创建一个【SimpleApplicationEventMulticaster】
 *
 *
 * 9、onRefresh();留给子类
 *      1）、子类重写这个方法， 在容器刷新的时候可以自定义逻辑
 *
 * 10、registerListeners();注册监听器
 *      1）、获取所有的监听器【ApplicationListener】，getBeanNamesForType(ApplicationListener.class)
 *      2）、添加到事件派发器中
 *      3）、派发之前步骤产生的事件
 *
 * 11、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean
 *
 *      1）、beanFactory.preInstantiateSingletons();初始化剩下的单实例bean
 *            1、获取所有的bean，依次进行初始化和创建对象
 *            2、获取bean的定义信息【RootBeanDefinition】
 *            3、不是抽象，是单例，不是懒加载
 *                  1）、判断是否实现【FactoryBean】，如果是工厂，就设置热部署为true
 *                  2）、如果不是，执行 getBean(beanName);
 *                      1、doGetBean(name, null, null, false)
 *                      2、先获取缓存中的单实例 bean， getSingleton(beanName)，所有创建过的bean都会被缓存起来
 *                          private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
 *                      3、缓存里没有，就开始创建

 *                          BeanFactory parentBeanFactory = getParentBeanFactory();获取bean工厂
 *                          markBeanAsCreated(beanName);标记当前bean正在被创建，防止多线程问题
 *                          RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);获取bean的定义信息
 *                      4、标记当前bean已经被创建
 *                      5、获取当前bean的定义信息
 *                      6、获取当前bean依赖的其他bean，如果有，按照getBean()把依赖的bean先创建出来
 *                      7、启动单实例bean的创建流程
 *                          1)、createBean(beanName, mbd, args);
 *                          2)、回调接口1      resolveBeforeInstantiation(beanName, mbdToUse);让BeanPostProcessor先拦截，返回代理对象
 *                              先回调这个方法，InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
 *                              上个方法有返回值，再回调这个方法，InstantiationAwareBeanPostProcessor.postProcessAfterInitialization()
 *                          3)、如果第三步的方法没有返回值，调用4
 *                          4)、doCreateBean(beanName, mbdToUse, args);
 *                              1、创建bean实例 createBeanInstance(beanName, mbd, args);
 *                                  利用工厂方法或者对象的构造器创建出bean实例
 *                              2、回调接口2         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 *                                  MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
 *                              3、bean的属性赋值，populateBean(beanName, mbd, instanceWrapper);
 *                                  1)、回调接口3
 *                                      InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
 *                                  2)、回调接口4
 *                                      InstantiationAwareBeanPostProcessor.postProcessPropertyValues()
 *                                  ==========属性赋值之前==========
 *                                  3)、属性赋值
 *                                      applyPropertyValues(beanName, mbd, bw, pvs);
 *			                    4、bean的初始化，initializeBean(beanName, exposedObject, mbd);
 *                        			1)、 invokeAwareMethods(beanName, bean); 执行实现的aware接口
 *                        		        	BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
 *                        		    2)、接口回调5 动态代理
 *                        		        BeanPostProcessor.postProcessBeforeInitialization()
 *	                                3)、执行初始化方法 invokeInitMethods(beanName, wrappedBean, mbd);
 *	                                    实现了接口 InitializingBean.afterPropertiesSet()
 *                                  4)、接口回调6 动态代理
 *                         		        BeanPostProcessor.postProcessAfterInitialization()
 *                              5、注册bean的销毁方法 registerDisposableBeanIfNecessary(beanName, bean, mbd);
 *                                  实现了接口DisposableBean.destroy()
 *                          5)、将创建的bean保存到缓存中
 *                                  addSingleton(beanName, singletonObject);
 *
 *                4、回调接口7
 *                     SmartInitializingSingleton.afterSingletonsInstantiated()
 *
 * 12、finishRefresh();
 *          LifecycleProcessor
 *              onRefresh()  onClose()
 *
 * 总结：
 *   1、spring容易在启动的时候，先会保存所有注册进来的bean的定义信息
 *      1）、xml注册bean：<bean>
 *      2）、注解注册bean：@Component
 *   2、spring容器会在何时的时机创建这些bean
 *      1）、用到这个bean的时候，利用getBean()创建bean，保存在容器中
 *      2）、统一创建剩下的所有bean，finishBeanFactoryInitialization()
 *   3、后置处理器：BeanPostProcessor
 *      1）、每一个bean创建完成，都会使用各种后置处理器处理，来增强bean的功能
 *          AutowiredAnnotationBeanPostProcessor,处理Autowired注解的自动注入
 *          AnnotationAwareAspectJAutoProxyCreator：来做aop功能
 *          AsyncAnnotationBeanPostProcessor：支持异步
 *   4、事件驱动模型：
 *      ApplicationListener：事件监听
 *      ApplicationEventMulticaster:事件派发
 *
 */
public class Demo {

	public static void main(String[] args) throws Exception {

		// spring-beans  spring-context

		// 资源定义,默认实现 AbstractResource
		Resource a1 = new FileSystemResource("");
		Resource a2 = new ByteArrayResource(null);
		Resource a3 = new UrlResource("");
		Resource a4 = new ClassPathResource("");
		Resource a5 = new InputStreamResource(null);


		// 资源访加载类，默认实现 DefaultResourceLoader
		ResourceLoader b1 = new DefaultResourceLoader();
		ResourceLoader b2 = new ClassRelativeResourceLoader(null);

		PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();


		// bean工厂，默认实现 DefaultListableBeanFactory
		BeanFactory c1 = new DefaultListableBeanFactory();

		// bean对象，描述bean的
		BeanDefinition d1 = new RootBeanDefinition();

		// spring的配置文件对象
		BeanDefinitionReader e1 = new XmlBeanDefinitionReader(null);
		BeanDefinitionReader e2 = new PropertiesBeanDefinitionReader(null);
		BeanDefinitionReader e3 = new GroovyBeanDefinitionReader(new SimpleBeanDefinitionRegistry());

		// 容器上下文
		ApplicationContext f1 = new AnnotationConfigApplicationContext();
		ApplicationContext f2 = new ClassPathXmlApplicationContext();
		ApplicationContext f3 = new GenericApplicationContext();




		// 注解创建bean对象
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SyyoService.class);
		// xml创建bean对象
		// new ClassPathXmlApplicationContext("dasd");
		SyyoService user = (SyyoService)ac.getBean("syyoService");
		System.out.println("========前======");
		System.out.println(user.toString());
		System.out.println("========后======");


		ClassPathResource resource = new ClassPathResource("bean.xml"); // <1>
		DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); // <2>
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); // <3>
		reader.loadBeanDefinitions(resource); // <4>

	}
}
